package phase1.part2;

import java.util.Iterator;
import java.util.Set;
import java.util.TreeSet;

/**
 * A Pattern contains the characters for a single transition.
 * 
 * @author Devin Wang
 * @version Nov 13, 2012
 */
public class Pattern {
	private String pattern;
	private Set<Character> accepting;

	/**
	 * Create a Pattern from its String representation. Create the initial accepting set of characters in the pattern.
	 * @param pattern The String representation of the pattern.
	 */
	public Pattern(String pattern) {
		this.pattern = pattern;
		accepting = new TreeSet<>();
        updateAccepting();
	}
	
	/**
	 * Add a character to the Pattern.
	 * @param c The character to add
	 */
    public void add(char c){
        if(!accepts(c)){
            accepting.add(c);
            updatePattern(c);
        }
    }
    
    /**
     * Form the initial accepting set of characters in the Pattern.
     */
    private void updateAccepting(){
        char[] chars = pattern.toCharArray();
        for(int i = 0; i < chars.length; i++) {
            if(chars[i] == '-' && i > 0 && i < chars.length - 1) {
                for (char c = chars[i-1]; c < chars[i+1]; c++) {
                    accepting.add(c);
                }
            }
            else{
                accepting.add(chars[i]);
            }
        }
    }
    
    /**
     * Add a character to the String representation of the pattern.
     * @param c The character to add
     */
    private void updatePattern(char c){
        String newPattern = "";
        boolean prevExists = false;
        char prev = 0;
        char curr = 0;
        boolean inGroup = false;
        Iterator<Character> itr = accepting.iterator();
        {
            while(itr.hasNext()){
                if(!prevExists){
                    prev = itr.next();
                    prevExists = true;
                    continue;
                }
                curr = itr.next();
                if(curr-prev == 1){
                    if(!inGroup){
                        inGroup = true;
                        newPattern = newPattern + Character.toString(prev) + "-";
                    }
                }
                else{
                    if(inGroup){
                        newPattern = newPattern + Character.toString(prev);
                        inGroup = false;
                    }
                    else{
                        newPattern = newPattern + Character.toString(prev);
                    }
                }
                prev = curr;
            }
            newPattern = newPattern + Character.toString(prev);
        }
        pattern = newPattern;
    }

    /**
     * Check whether a character is in the pattern.
     * @param c The character to check
     * @return <CODE>true</CODE> if the character is in the accepting set, <CODE>false</CODE> if not
     */
	public boolean accepts(char c) {
		return accepting.contains(c);
	}
    
	/**
	 * Get the String representation of the pattern.
	 * @return pattern
	 */
    public String getPattern(){
        return pattern;
    }
    
    /**
     * Get the accepting set of the pattern.
     * @return accepting
     */
    public Set<Character> getAccepting(){
    	return accepting;
    }

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (!(obj instanceof Pattern))
			return false;
		Pattern other = (Pattern) obj;
		if (accepting == null) {
			if (other.getAccepting() != null)
				return false;
		}
        else if (!accepting.containsAll(other.getAccepting()))
			return false;
        else if (!other.getAccepting().containsAll(accepting))
            return false;
		return true;
	}

	@Override
	public String toString() {
		return "Pattern [pattern=" + pattern + ", accepting=" + accepting + "]";
	}
}